/*=============================================================================
    jibits/popup.js
    Copyright (C) 2008-2009, Donald W. Griffin
    All rights reserved.
    [MIT license :: see license.txt for details]
=============================================================================*/
$module("jibits.popup");

$requires("zjs.browser");

$requires("jibits.widget");

$namespace(jibits, {

Popup : $class(jibits.Widget,
{
    ctor : function (id)
    {
        $super(arguments).call(this, id);
        this.zIndex = 10;
    },

    setVisible : function (vis)
    {
        if (vis)
            this.setStyle({ zIndex : this.zIndex });

        $super(arguments).call(this, vis);
    },

    /*
    IE is infamous for having problems with overlapping certain elements. There is
    (mercifully) a hack called the "iframe shim" that can get around this most
    problematic issue. See these articles for starters:

        http://dotnetjunkies.com/weblog/jking/archive/2003/07/21/488.aspx
        MSDN Article ID: 177378 (http://support.microsoft.com/kb/177378)
        http://www.gexperts.com/articles/portal-menus.asp
    */
    "?zjs.browser.ie" : function ()
    {
        function cleanup ()
        {
            if (!this.iframe)
                return;
            this.iframe.destroy();
            this.iframe = null;
        }

        return (
        {
            ctor : function (id)
            {
                $super(arguments).call(this, id);

                this.padding = $size();
            },

            destroy : function ()
            {
                $super(arguments).call(this);
                cleanup.call(this);
            },

            remove : function ()
            {
                $super(arguments).call(this);
                cleanup.call(this);
            },

            setPadding : function (pad)
            {
                this.padding = pad;

                if (this.isVisible())
                    this.pollSoon();
            },

            sync : function ()
            {
                $super(arguments).call(this);

                if (!this.elem())
                    cleanup.call(this);
                else
                {
                    if (!this.iframe)
                        this.iframe = new jibits.IFrameShim(this.id + "_iframeShim");
                    this.iframe.follow(this.elem(), this.padding);
                }
            }
        });
    } // called if condition is true
}),

//-----------------------------------------------------------------------------

/*
This class encapsulates the iframe element that tricks IE 5.5+ into proper
rendering over windowed elements.
*/
IFrameShim : $class(jibits.Widget,
{
    ctor : function (id)
    {
        $super(arguments, this);
    },

    destroy : function ()
    {
        $super(arguments, this);
        var el = this.elem();
        jibits.removeElem(el);
    },

    /**
    This method aligns this ifram under the given element (plus padding).
    */
    follow : function (ref, pad)
    {
        ref = $elem(ref);
        var el = this.elem(), pel = ref.parentNode;

        if (!el)
        {
            // this method sets all the details before adding to the DOM:
            el = jibits.newChild(pel, "iframe", this.id,
                                    { frameBorder:0,
                                      style:
                                        { display : "none",
                                          filter  : "alpha(opacity=0)",
                                          position: "absolute" }
                                    });

            this.connect(); // let our Widget-ness know about the element
        }

        var vis = this.isVisible(), elvis = ref && jibits.isVisible(ref);
        if (vis && !elvis)
        {
            this.hide();
            return;
        }

        var r = jibits.getTotalOffsetRect(ref);

        this.setStyle({
            left   : r.L() + "px",
            top    : r.T() + "px",
            width  : (r.W() + (pad ? pad.w : 0)) + "px",
            height : (r.H() + (pad ? pad.h : 0)) + "px",
            zIndex : ref.style.zIndex - 1
        });

        this.moveBelow(ref);

        if (!vis && elvis)
            this.show();
    }
})

});
